package main;

/**
 * @author Ken "David" McClain
 * @author Zach Turk
 */

import java.awt.Color;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;

public class SceneGraphNode implements Serializable {
	/** Serial ID */
	private static final long serialVersionUID = -1499069477909771295L;
	
	public float scale;
	public float rotation;
	public float translateX;
	public float translateY;
	public float CoMX;
	public float CoMY;
	private List<SceneGraphNode> children;
	private boolean pickable;
	
	public float colorRed = 0f, colorGreen = 0f, colorBlue = 0f;
	
	public SceneGraphNode() {
		this(true);
	}
	
	public SceneGraphNode(boolean pickable) {
		scale = 1;
		children = new LinkedList<SceneGraphNode>();
		this.pickable = pickable;
		setColorRandom();
	}
	
	public SceneGraphNode(boolean pickable, Color color) {
		this(pickable);
		setColor(color);
	}
	
	public void addChild(SceneGraphNode node) {
		if (node == this)
			throw new IllegalArgumentException();
		children.add(node);
	}
	
	public void removeChild(SceneGraphNode node) {
		synchronized (children) {
			children.remove(node);
		}
	}
	
	public final void render(GLAutoDrawable drawable) {
		GL2 gl = drawable.getGL().getGL2();
		
		gl.glPushMatrix();
		gl.glTranslatef(translateX + CoMX, translateY + CoMY, 0);
		gl.glRotatef(rotation, 0, 0, 1);
		gl.glTranslatef(-CoMX, -CoMY, 0);
		gl.glScalef(scale, scale, scale);
		
		gl.glColor3f(colorRed, colorGreen, colorBlue);
		
		synchronized(children) {
			if (children.size() == 0)
				renderGeometry(drawable);
			else {
				for (int i = 0; i < children.size(); i++) {
					SceneGraphNode child = children.get(i);
					if (child != null) 
						child.render(drawable);
				}
				//for (SceneGraphNode child : children)
					//child.render(drawable);
			}
		}
		gl.glPopMatrix();
	}
	
	public void renderGeometry(GLAutoDrawable drawable) {
	}
	
	public final List<SceneGraphNode> getPicked(GLAutoDrawable drawable) {
		List<SceneGraphNode> picked = new LinkedList<SceneGraphNode>();
		GL2 gl = drawable.getGL().getGL2();
		gl.glRenderMode(GL2.GL_SELECT);		
		getPicked(drawable, picked);
		gl.glRenderMode(GL2.GL_RENDER);
		return picked;
	}

	private boolean getPicked(GLAutoDrawable drawable, List<SceneGraphNode> picked) {
		GL2 gl = drawable.getGL().getGL2();
		boolean pickPending = false;
		
		gl.glPushMatrix();
		gl.glTranslatef(translateX + CoMX, translateY + CoMY, 0);
		gl.glRotatef(rotation, 0, 0, 1);
		gl.glTranslatef(-CoMX, -CoMY, 0);
		gl.glScalef(scale, scale, scale);
		if (children.size() == 0) {
			renderGeometry(drawable);
			if (gl.glRenderMode(GL2.GL_SELECT) > 0)
				if (pickable)
					picked.add(this);
				else
					pickPending = true;
		} else {
			for (SceneGraphNode child : children)
				pickPending = child.getPicked(drawable, picked) || pickPending;
			if (pickable && pickPending) {
				picked.add(this);
				pickPending = false;
			}
		}
		gl.glPopMatrix();
		return pickPending;
	}
	
	public void setColor(Color color) {
		colorRed   = (float)   color.getRed() / 255;
		colorGreen = (float) color.getGreen() / 255;
		colorBlue  = (float)  color.getBlue() / 255;
	}
	
	public void setColorRandom() {
		Random rand = new Random();
		colorRed   = rand.nextFloat();
		colorGreen = rand.nextFloat();
		colorBlue  = rand.nextFloat();
	}
}
